iT邦幫忙

2022 iThome 鐵人賽

DAY 15
0
Web 3

當 APP develop 遇上 web3 與 Metaverse 浪潮 系列 第 15

[Day 拾伍] 來開發元宇宙中藥鋪吧-3 如何與組件進行互動?

  • 分享至 

  • xImage
  •  

首先讓我們回到最初的官方範例
https://codesandbox.io/s/basic-demo-rrppl0y8l4

import { useRef, useState } from 'react'
import { Canvas, useFrame } from '@react-three/fiber'

function Box(props) {
  // This reference gives us direct access to the THREE.Mesh object
  const ref = useRef()
  // Hold state for hovered and clicked events
  const [hovered, hover] = useState(false)
  const [clicked, click] = useState(false)
  // Subscribe this component to the render-loop, rotate the mesh every frame
  useFrame((state, delta) => (ref.current.rotation.x += delta))
  // Return the view, these are regular Threejs elements expressed in JSX
  return (
    <mesh
      {...props}
      ref={ref}
      scale={clicked ? 1.5 : 1}
      onClick={(event) => click(!clicked)}
      onPointerOver={(event) => hover(true)}
      onPointerOut={(event) => hover(false)}>
      <boxGeometry args={[1, 1, 1]} />
      <meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} />
    </mesh>
  )
}

export default function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} />
      <pointLight position={[-10, -10, -10]} />
      <Box position={[-1.2, 0, 0]} />
      <Box position={[1.2, 0, 0]} />
    </Canvas>
  )
}

先分別放置 hovered 與 clicked 的State

const [hovered, hover] = useState(false)
const [clicked, click] = useState(false)

然後就可以像一般在 新增事件一樣來使用它

<mesh
      {...props}
      ref={ref}
      scale={clicked ? 1.5 : 1}
      onClick={(event) => click(!clicked)}
      onPointerOver={(event) => hover(true)}
      onPointerOut={(event) => hover(false)}>  
</mesh>

好, 讓我們回到中藥舖

接下來,我們要讓櫃子跟抽屜....可。以。打。開。

讓我們修改小抽屜的元件


  function MBox({ id, lineH, ...props }) {
    // This reference gives us direct access to the THREE.Mesh object
    const ref = useRef()
    // Hold state for hovered and clicked events
    const [hovered, hover] = useState(false)
    const [clicked, click] = useState(false)

    const [hoveredContent, hoverContent] = useState(false)
    const [clickedContent, clickContent] = useState(false)
    // Subscribe this component to the render-loop, rotate the mesh every frame
    useFrame((state, delta) => {
     
    return (
      <group
        {...props}
        ref={ref}
        onPointerOver={(event) => hover(true)}
        onPointerOut={(event) => hover(false)}
        position={[-1.33, lineH, hovered ? -0.1 : -0.13]}>
        <ModelCMDpack
          onClicked={clicked && clickedContent}
          rotation={[0.4, 0, 0]}
          scale={[0.13, 0.13, 0.15]}
          position={[-0.01, 0.04 + 0.01, clicked ? 0.5 : 0.21]}
          onClick={(event) => {
            getSelectBox(`R${id.row}:C${id.col}`, clicked)
          }}
        />
        <group scale={[0.13, 0.13, 0.45]}>
          <group position={[0, 0, clicked ? 0.8 - 0.35 : -0.13]}>
            <mesh scale={[1, 1, 1 / 2]} onClick={(event) => click(!clicked)} position={[-0.01, -0.13, 1.01 - 0.05]}>
              <boxGeometry args={[1, 1 * 0.5, 0.5]} />
              <meshStandardMaterial transparent opacity={0.01} color={hovered ? 'hotpink' : 'orange'} />
            </mesh>
            <mesh
              onPointerOver={(event) => hoverContent(true)}
              onPointerOut={(event) => hoverContent(false)}
              onClick={(event) => {
                clickContent(!clickedContent)
              }}
              position={[-0.01, -0.13, 0.15]}>
              <boxGeometry args={[2, 1, 0.5]} />
              <meshStandardMaterial transparent opacity={1} color={hoveredContent ? 'Yellow ' : getRandomColor()} />
            </mesh>
            <mesh geometry={nodes.Cube023.geometry} material={materials['Old Wooden Safe Box Wood 2.010']} />
            <mesh geometry={nodes.Cube023_1.geometry} material={materials['Old Wooden Safe Box Wood 2.010']} />
            <mesh
              geometry={nodes.TorusOG.geometry}
              material={materials['Old Wooden Safe Box Wood 2.011']}
              position={[0.01, -0.13, 1.01]}
              rotation={[Math.PI / 2, 0, 0]}
              scale={[0.11, 0.03, 0.12]}
            />
            <mesh
              geometry={nodes.底座OG.geometry}
              material={materials['Old Wooden Safe Box Wood 2.011']}
              position={[0.01, -0.01, 1]}
              rotation={[Math.PI / 2, 0, 0]}
              scale={[0.09, 0.01, 0.09]}
            />
          </group>
        </group>
      </group>
    )
  }

搭啦~ 完成了

第一次點擊打開,再點一次關閉

onClick={(event) => click(!clicked)}

利用三元運算子 條件結果? A:B 的方式 更改抽屜的打開距離

lineH 則是前幾天利用陣列產生一堆小櫃子的變數

position={[-1.33, lineH, clicked ? 0.2 : -0.13]}


上一篇
[Day 拾肆] 來開發元宇宙中藥鋪吧-2 如何簡化檔案與組件
下一篇
[Day 拾陸] 來開發元宇宙中藥鋪吧-4 來做扁額吧
系列文
當 APP develop 遇上 web3 與 Metaverse 浪潮 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言